/*
 * Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
 * Copyright (c) 2025 Kaiwen Zhang <zhangkaiwengamer@163.com>
 * All rights reserved
 */

#ifndef COMBO_MULTI_BUTTON_H_
#define COMBO_MULTI_BUTTON_H_

#include <stdint.h>
#include <string.h>

// According to your need to modify the constants.
#define TICKS_INTERVAL 10				   // ms
#define DEBOUNCE_TICKS 3				   // MAX 7 (0 ~ 7)
#define SHORT_TICKS (300 / TICKS_INTERVAL) // 短按触发时间,300ms.两次短按间隔不超过300ms则视为双击
#define LONG_TICKS (1000 / TICKS_INTERVAL) // 长按触发时间,1000ms

#define LONG_HOLD_MAX_TICKS (100 / TICKS_INTERVAL) // 长按中的最长触发间隔,100ms
#define LONG_HOLD_MIN_TICKS (30 / TICKS_INTERVAL)  // 长按中的最短触发间隔,30ms

#define SHORT_COMBO_DETECT_TICKS (SHORT_TICKS - (50 / TICKS_INTERVAL)) // 组合短按检测时间 250ms~300ms
#define LONG_COMBO_DETECT_TICKS (100 / TICKS_INTERVAL)				   // 组合长按检测时间 0~100ms

#define BUTTON_MAX_NUMBER 32 // 按键最大数量
typedef void (*BtnCallback)(void *);

typedef enum
{
	PRESS_DOWN = 0,
	PRESS_UP,
	PRESS_REPEAT,
	SINGLE_CLICK,
	DOUBLE_CLICK,
	LONG_PRESS_START,
	LONG_PRESS_HOLD,
	COMBO_SHORT_DOWN,
	COMBO_LONG_DOWN,
	number_of_event,
	NONE_PRESS
} PressEvent;
typedef struct tagComboButtonId_T
{
	uint8_t current_button_id;
	uint8_t short_combo_id; // BUTTON_MAX_NUMBER表示不启用短按组合检测
	uint8_t long_combo_id;	// BUTTON_MAX_NUMBER表示不启用长按组合检测
} ComboButtonId_T;

typedef struct Button
{
	uint16_t ticks;
	uint8_t repeat : 4;
	uint8_t event : 4;
	uint8_t state : 3;
	uint8_t debounce_cnt : 3;
	uint8_t active_level : 1;
	uint8_t button_level : 1;
	uint8_t button_id;

	ComboButtonId_T *pCombo;	  // 挂载的组合按键
	uint8_t combo_len;			  // 数组长度
	uint8_t match_combo_short_id; // 组合短按时另一个按键的id
	uint8_t match_combo_long_id;  // 组合长按时另一个按键的id

	uint8_t (*hal_button_Level)(uint8_t button_id_);
	BtnCallback cb[number_of_event];
	struct Button *next;
} Button;

#ifdef __cplusplus
extern "C"
{
#endif

	void button_init(struct Button *handle, uint8_t (*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id);
	void button_mount_combo(struct Button *handle, ComboButtonId_T *combin, uint8_t combin_len); // 组合按键挂载
	void button_attach(struct Button *handle, PressEvent event, BtnCallback cb);
	PressEvent get_button_event(struct Button *handle);
	int button_start(struct Button *handle);
	void button_stop(struct Button *handle);
	void button_ticks(void);
#ifdef __cplusplus
}
#endif

#endif
